using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using LiquidFireArts.Wormhole.Misc;


namespace Unibot
{
    class LevelScreen : Screen
    {
        //public int Gravity = 5;

        //WARNING: it only sorts by initial position... therefore it is not dynamic!!!
//        private ArrayList elements; //currently sorted by x value, change later.. make custom rectangle class maybe

        private Camera camera;
        private Timer timer;
        private bool timerrestarted;
        private bool endlevel;

        private UnibotGame theGame;

        float _Seconds;                     // the seconds of th elast update

        private CollisionDetector2D detector;
        Brush objectBrush;
        TextureGenerator generator;

        private List<Element> activeElements;
        private List<Element> passiveElements;

        public LevelScreen(UnibotGame game)
            : base(game)
        {
            this.theGame = game;

            // game init
            //detector = new CollisionDetector2D();
            //detector.OnCollision += new CollisionDetected(Detector_OnCollision);
            generator = game.getTextureGenerator();
            activeElements = new List<Element>();
            passiveElements = new List<Element>();

            //camera = new Camera(player); // let's have a parallax system? would be pretty sweet, like how SMB backgrounds scroll slower than the foreground basically
            timer = new Timer(TimeSpan.Zero, game.GraphicsDevice);
            timerrestarted = false;
            endlevel = false;

            // player init (could be encapsulated as a general method):
            Vector2 p_position = new Vector2(0, 0);
            Texture2D p_texture = game.Content.Load<Texture2D>("Sprites/Unibot");
            SpriteShape p_shape = new SpriteShape(p_position, p_texture, new Rectangle(0, 0, p_texture.Width, p_texture.Height), 128);
            Player player = new Player(PlayerIndex.One, p_texture, p_shape, p_position); // create player
            activeElements.Add(player); // add to list

            // platform init (could be encapsulated as a general method):
            objectBrush = new Brush(2, 2);
            // shape creation:
            Vector2 plat_position = new Vector2(0,600);
            List<Vector2> corners = new List<Vector2>();
            corners.Add(new Vector2(0, 500));  // left top 
            corners.Add(new Vector2(1280, 500));
            corners.Add(new Vector2(1280, 600));
            corners.Add(new Vector2(0, 600));
            Shape plat_shape = new Polygon(new LineStrip(corners)); // create shape from lines
            Texture2D plat_texture = generator.GeometryFilledWithBorder(plat_shape, Color.WhiteSmoke, Color.Black, objectBrush);
            // add bottom as passive geometry to the collision detector
            Platform bottom = new Platform(plat_texture, plat_shape, plat_position);
            passiveElements.Add(bottom);

            // platform2 init
            Vector2 plat2_position = new Vector2(700, 500);
            List<Vector2> corners2 = new List<Vector2>();
            corners2.Add(new Vector2(0, 0));
            corners2.Add(new Vector2(100, 0));
            corners2.Add(new Vector2(100, 100));
            corners2.Add(new Vector2(0, 100));
            Shape plat2_shape = new Polygon(new LineStrip(corners2));
            Texture2D plat2_texture = generator.GeometryFilledWithBorder(plat2_shape, Color.Bisque, Color.Black, objectBrush);
            Platform block = new Platform(plat2_texture, plat2_shape, plat2_position);
            passiveElements.Add(block);

            // triangle init
            Vector2 plat4_position = new Vector2(400, 550);
            List<Vector2> corners4 = new List<Vector2>();
            corners4.Add(new Vector2(0, 50));
            corners4.Add(new Vector2(100, 50));
            corners4.Add(new Vector2(100, 0));
            Shape plat4_shape = new Polygon(new LineStrip(corners4));
            Texture2D plat4_texture = generator.GeometryFilledWithBorder(plat4_shape, Color.BlueViolet, Color.Black, objectBrush);
            Platform triangle = new Platform(plat4_texture, plat4_shape, plat4_position);
            passiveElements.Add(triangle);

            Vector2 plat3_position = new Vector2(900, 510);
            List<Vector2> corners3 = new List<Vector2>();
            corners3.Add(new Vector2(0, 0));
            corners3.Add(new Vector2(64, 0));
            corners3.Add(new Vector2(64, 64));
            corners3.Add(new Vector2(0, 64));
            Shape plat3_shape = new Polygon(new LineStrip(corners3));
            Texture2D plat3_texture = game.Content.Load<Texture2D>("Sprites/sprite_sheet");
            AnimatedPlatform fireball = new AnimatedPlatform(plat3_texture, plat3_shape, plat3_position);
            passiveElements.Add(fireball);
        }

        public override void Draw(GameTime gameTime)
        {
            //Matrix cameramatrix = camera.getCameraTransformationMatrix();
            //theGame.getSpriteBatch().Begin(SpriteBlendMode.AlphaBlend, SpriteSortMode.BackToFront, SaveStateMode.None, cameramatrix);
            SpriteBatch sb = theGame.getSpriteBatch();
            sb.Begin();
            foreach (Element a in activeElements)
            {
                a.Draw(sb);
            }
            foreach (Element p in passiveElements)
            {
                p.Draw(sb);
            }
            //theGame.getSpriteBatch().Draw(_BottomTex, objectBrush.GetTexturePosition(bottom.Position), Color.White);
            sb.End();

            timer.Draw();
        }

        public override void Update(GameTime gameTime)
        {
            // state update:
            // loop through our Elements, calling their update method
            foreach (Element a in activeElements)
            {
                a.update(gameTime);
            }
            foreach (Element p in passiveElements)
            {
                p.update(gameTime);
            }

            // collision checks:
            // checks mobile active elements vs. passive ones right now
            // in the future with will be optimized somehow
            // maybe our methods need to pass in GameTime obj...
            foreach (Element a in activeElements)
            {
                foreach (Element p in passiveElements)
                {
                    // to start, each object only has 1 bounding box in TypeA list                    
                    if (CollisionDetector2D.ShapeShapeIntersecting(a.TypeA[0], p.TypeA[0])) // collision occurred
                    {
                        a.onCollisionWith(p,gameTime); // resolve
                        p.onCollisionWith(a,gameTime); // resolve
                    }
                }
            }

            //start timer on first loop
            if (!timerrestarted)
            {
                timer.ResetTimer(gameTime.TotalRealTime);
                timerrestarted = true;
            }
            
            //Set Camera
            //camera.Update(player);

            //Set Timer
            timer.Update(gameTime.TotalRealTime);

            //Cheap Restart
            MyGamePadState padstate = MyGamePad.GetState(PlayerIndex.One);
            if (padstate.Buttons.L2 == ButtonState.Pressed)
            {
                CheapRestart();
            }
        }



        //Get rid of this... as it's probably bad for memory...?
        private void CheapRestart()
        {
            game.setCurrentState(GameState.InLevel);
            game.changeScreen(new LevelScreen(game));
        }
    }
}